import AMapLoader from '@amap/amap-jsapi-loader';
import china from '/@/assets/lngLat/china.ts';
import chinaInner from '/@/assets/lngLat/chinaInner.ts';
import { createCircle, createIcon, getCenter, getLonLat, typeToIcon } from '/@/assets/mapUtils/commonFun.ts';
import { aircraftContent, alarmIcon, female, male } from '/@/components/chinaMap/chinaHooks.ts';
import { isFunction } from '/@/utils/is.ts';
import { Callback, ExtDataType, InitMap, MarkerOption, ResultType } from '/@/assets/mapUtils/mapFunTypes.ts';
import { defaultOption, getZoom, mapKey, mapPlugin } from '/@/assets/mapUtils/mapConstant.ts';

let AMap = null;
export const Map = {
    map: null,
    overlayGroup: null, // 地图中marker
    circleGroup: null, //直升机背景圆
    cluster: null, //直升机marker点聚合图层
    airMarkerList: [], //直升机markerList
    placeSearch: null, //地点查询
    marker: null, // 健康终端报警
    infoWindow: null, //地图弹窗
    driveLine: null, // 导航轨迹线
    emergencyMarker: null, // 应急人员marker
    /**
     * @desc 地图舒适化
     * @param el dom元素 id选择器
     * @param option 地图配置
     * @param innerLineOption 内轨迹线配置
     * @param outlineOption 外轨迹线配置
     */
    initMap({ el, option, innerLineOption, outerLineOption }: InitMap) {
        return new Promise((resolve) => {
            AMapLoader.load({
                key: mapKey, // 申请好的Web端开发者Key，首次调用 load 时必填
                version: '2.0', // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
                plugins: mapPlugin, // 需要使用的的插件列表，如比例尺'AMap.Scale'等
            }).then((res) => {
                AMap = res;
                const { zoom, center, mapStyle } = { ...defaultOption, ...option };
                //基本地图加载
                this.map = new AMap.Map(el, {
                    resizeEnable: true,
                    center: center,
                    zoom: zoom,
                    mapStyle: 'amap://styles/' + mapStyle,
                    version: '2.0',
                });
                // 异步同时加载多个插件
                new AMap.plugin(mapPlugin, () => {
                    if (outerLineOption) {
                        this.drawInnerLine(innerLineOption);
                        this.drawOutLine(outerLineOption);
                    } else {
                        this.drawInnerLine();
                        this.drawOutLine();
                    }
                });
                resolve();
            });
        });
    },
    /**
     *#desc 获取地图中心点
     */
    getMapCenter() {
        return this.map.getCenter();
    },

    /**
     * @desc 中国外层边界线
     */
    drawOutLine(outerLineOption = {}) {
        let line = {
            strokeColor: '#2384dd',
            strokeWeight: 3,
            isOutline: false,
        };
        let geoJson = new AMap.GeoJSON({
            geoJSON: china,
            getPolygon: function (geoJson: string, lngLats: any) {
                return new AMap.Polyline({
                    path: lngLats[0],
                    ...line,
                    ...outerLineOption,
                });
            },
        });
        this.map.add(geoJson);
    } /**
     * @desc 中国内层边界线
     */,
    drawInnerLine(innerLineOption = {}) {
        let line = {
            isOutline: true,
            outlineColor: '#2692fc',
            borderWeight: 1,
            strokeColor: '#88b9f8',
            strokeWeight: 1,
            strokeOpacity: 0.8,
        };
        let geoJson = new AMap.GeoJSON({
            geoJSON: chinaInner,
            getPolygon: function (geoJson: string, lngLats: any) {
                return new AMap.Polyline({ path: lngLats[0], ...line, ...innerLineOption });
            },
        });
        this.map.add(geoJson);
    },
    /**
     * @desc 设置地图级别与中心点
     * @param center 【lon,lat】
     * @param zoom 地图层级
     * */
    setZoomCenter(center, zoom = 12) {
        this.map && this.map.setZoomAndCenter(zoom, center);
    },
    /**
     * @desc 清空当前地图上除了边界线的覆盖物
     */
    removeOverlayGroup() {
        this.clearAircraft();
        this.clearOverlay();
        this.clearAirRange();
        this.clearMarker(); //
        if (this.airMarkerList) {
            this.airMarkerList = [];
        }
        this.clearActiveHospital();
        this.clearInfoModal();
        // this.map.remove(this.airMarkerList);
    }, //
    /**
     * @desc 创建覆盖物组，用于批量处理点 （控制显隐，点击事件等）
     * @param result
     * @param extData
     * @param callback
     * @param computedCenter 是否计算中心点
     */
    createOverlay(result: ResultType[], extData?: ExtDataType, callback?: Callback, computedCenter?: boolean) {
        this.removeOverlayGroup();
        this.overlayGroup = new AMap.OverlayGroup();
        let list = getLonLat(result);
        let center = getCenter(list);
        let zoom = getZoom(list);
        if (computedCenter) {
            this.setZoomCenter(center, zoom);
        }
        for (let i = 0; i < result.length; i++) {
            let { type, lon, lat, lng, centerResource } = result[i];
            if (lng) {
                lon = lng;
            }
            if (!lon || !lat || !type) {
                continue;
            }
            // 创建一个 Icon
            let startIcon = typeToIcon(type, centerResource);
            // 将 icon 传入 marker
            let startMarker = new AMap.Marker({
                // 点的坐标
                position: [lon, lat], // 指定点的icon，也可以是个url ，但这样就不能对图片进行设置了
                icon: startIcon, //启用点击事件 如果需要点击事件，必须开启
                clickable: true, //点额外携带的数据，用户自定义属性，支持JavaScript API任意数据类型
                offset: [-18, -32],
                maxZoom: 14,
                extData: result[i],
                label: {
                    content: isFunction(extData?.content) && extData?.content(result[i]),
                },
                ...extData?.extOption,
            });
            // 可以调用setExtData（）设置自定义属性
            //将组 挂载到地图上
            this.overlayGroup.setMap(this.map);
            //将需要批量控制的点放到一个组中，通过控制组，就可以操作组内所有所有覆盖物
            this.overlayGroup.addOverlay(startMarker);
        }

        this.overlayGroup.on('click', function (e) {
            //拿到点中携带的数据
            if (!isFunction(callback)) return;
            callback(e.target.getExtData());
        });
    },
    clearOverlay() {
        if (this.overlayGroup) {
            this.map.remove(this.overlayGroup);
            this.overlayGroup.setMap(null);
            this.overlayGroup = null;
        }
    },

    /**
     * @desc 创建直升机marker
     * @param result
     */
    createAircraft(result: ResultType[]) {
        this.removeOverlayGroup();
        this.clearActiveHospital();
        if (!Array.isArray(result) && result.length == 0) return;
        this.createAirRange(result);
        let that = this;
        let arr = result.map((item) => ({ weight: 4, lnglat: [item.lon, item.lat], params: item.name }));
        let count = 4;
        this.cluster = new AMap.MarkerClusterer(
            that.map, // 地图实例
            arr,
            {
                renderMarker: (context) => {
                    let factor = Math.pow(context.count / count, 1 / 18);
                    let div = document.createElement('div');
                    div.className = 'render-air';
                    let Hue = 180 - factor * 180;
                    let size = Math.round(30 + Math.pow(context.count / count, 1 / 5) * 20);
                    div.style.width = div.style.height = size + 'px';
                    div.innerHTML = aircraftContent() || context.count;
                    div.style.color = '#fff';
                    div.style.fontSize = '14px';
                    context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2));
                    context.marker.setContent(div);
                    // this.airMarkerList.push(context.marker);
                    // context.marker.on('click', () => {
                    //     console.log('data', context);
                    // });
                },
            }
        );
        // this.cluster.setMap(this.map);
    },
    clearAircraft() {
        if (this.cluster) {
            this.cluster.setMap(null);
            // this.map.remove(this.cluster);
            // this.cluster = null;
        }
    } /**
     * @desc 飞机范围
     * @param list
     */,
    createAirRange(list: ResultType[]) {
        this.removeOverlayGroup();
        this.circleGroup = new AMap.OverlayGroup();
        for (let i = 0; i < list.length; i++) {
            let circle = createCircle({ lon: list[i].lon, lat: list[i].lat });
            this.circleGroup.setMap(this.map);
            this.circleGroup.addOverlay(circle);
        }
    },
    clearAirRange() {
        if (this.circleGroup) {
            this.map.remove(this.circleGroup);
            this.circleGroup = null;
        }
    } /**
     * @desc 地方医院医疗点显示
     * @param cityCode 城市code
     * @param keywords 搜索名称
     */,
    createActiveHospital(cityCode: string, keywords = '医院') {
        this.removeOverlayGroup();
        this.clearActiveHospital();
        if (!cityCode) return;
        if (!this.placeSearch) {
            this.placeSearch = new AMap.PlaceSearch({
                pageSize: 30, // 单页显示结果条数
                pageIndex: 1, // 页码
                city: cityCode, // 兴趣点城市
                citylimit: true, //是否强制限制在设置的城市内搜索
                map: this.map, // 展现结果的地图实例
                // panel: 'map_hospital', // 结果列表将在此容器中进行展示。
                autoFitView: false, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
            });
        }
        this.placeSearch.setCity(cityCode);
        //关键字查询
        this.placeSearch.search(keywords);
    },
    clearActiveHospital() {
        if (this.placeSearch) {
            this.placeSearch.clear();
        }
    },
    createMarker(option: MarkerOption, callbck?: Callback) {
        this.clearMarker();
        let { lon, lat, zoom = 12 } = option;
        const icon = createIcon({ icon: alarmIcon, iconSize: [36, 42], imageSize: [36, 42] });
        let str = option?.realName && option?.eventType_dictText ? `${option?.realName},${option?.eventType_dictText}` : `${option?.realName}`;
        this.marker = new AMap.Marker({
            position: [lon, lat],
            icon: icon,
            offset: new AMap.Pixel(0, 0), //设置偏移量
            label: {
                content: `<div class="alarm-content" > 
                                <div>${str}</div>
                          </div>`,
                offset: new AMap.Pixel(0, -9),
                direction: 'top',
            },
        });
        this.map.add(this.marker);
        this.map.setZoomAndCenter(zoom, [lon, lat]);
        this.marker.on('click', callbck);
    },
    clearMarker() {
        if (this.marker) {
            this.marker?.setMap(null);
            this.marker = null;
        }
    },
    /**
     * @desc 创建地图详情弹窗
     *
     * */
    createInfoModal({ option, content }) {
        let { lat, lng } = option;
        this.infoWindow = new AMap.InfoWindow({
            position: [lng, lat],
            offset: new AMap.Pixel(-5, -25),
            content: content,
            closeWhenClickMap: true,
        });
        this.infoWindow.open(this.map);
    },
    clearInfoModal() {
        if (this.infoWindow) {
            this.infoWindow?.setMap(null);
            this.infoWindow = null;
        }
    },
    /**
     * @desc 计算两个坐标点的距离
     * @param {Array} listA 坐标点数组
     * @param {Array} listB 坐标点数组
     * @return {Number} 距离
     */
    getDistance(listA: number[], listB: number[]) {
        let lnglatA = new AMap.LngLat(listA[0], listA[1]);
        let lnglatB = new AMap.LngLat(listB[0], listB[1]);
        return lnglatA.distance(lnglatB);
    },
    /**
     * @desc 计算两个坐标点的驾车时间
     * @param {Array} listA 坐标点数组
     * @param {Array} listB 坐标点数组
     * @param {Function} callback 回调
     * @return {Number} 时间
     */
    getDriveTime(listA: number[], listB: number[], callback?: Callback) {
        let lnglatA = new AMap.LngLat(listA[0], listA[1]);
        let lnglatB = new AMap.LngLat(listB[0], listB[1]);
        const drivingOptions = {
            policy: AMap.DrivingPolicy.LEAST_TIME,
        };
        let driving = new AMap.Driving(drivingOptions);
        return new Promise((resolve, reject) => {
            driving.search(lnglatA, lnglatB, (status, result) => {
                if (status === 'complete') {
                    // console.log('result', result);
                    if (callback && isFunction(callback)) {
                        callback(result);
                    }
                    return resolve(result.routes[0]);
                }
            });
        });
    },

    /**
     * @desc 创建导航轨迹线路
     * @param {Array} listA 坐标点数组
     * @param {Array} listB 坐标点数组
     *
     */
    createNaviLine(listA: number[], listB: number[]) {
        this.clearNaviLine();
        let lnglatA = new AMap.LngLat(listA[0], listA[1]);
        let lnglatB = new AMap.LngLat(listB[0], listB[1]);
        const drivingOptions = {
            policy: AMap.DrivingPolicy.LEAST_TIME,
            map: this.map,
            autoFitView: true,
            // panel: 'driving-panel',
        };
        this.driveLine = new AMap.Driving(drivingOptions);
        this.driveLine.search(lnglatA, lnglatB, (status, result) => {
            if (status === 'complete') {
                // console.log('result', result);
            }
        });
        this.driveLine.on('error', function (result) {
            let str = '定位失败：';
            console.log('error', result);
            switch (result.info) {
                case 'PERMISSION_DENIED':
                    str += '浏览器阻止了定位操作';
                    break;
                case 'POSITION_UNAVAILBLE':
                    str += '无法获得当前位置';
                    break;
                case 'TIMEOUT':
                    str += '定位超时';
                    break;
                default:
                    str += '未知错误';
                    break;
            }
            console.log(str);
            return false;
        });
    },
    /**
     * @desc 清除导航轨迹线路
     */
    clearNaviLine() {
        if (this.driveLine) {
            this.driveLine.clear();
        }
    },
    /**
     * @desc 创建应急人员Marker
     */
    createEmergencyMarker(option) {
        this.clearEmergencyMarker();
        const { sex, address, name, position } = option;
        const icon = sex == '1' ? female : male;
        this.emergencyMarker = new AMap.Marker({
            position: position,
            icon: createIcon({ icon: icon, iconSize: [36, 36], imageSize: [36, 36] }),
            offset: new AMap.Pixel(0, 0), //设置偏移量
            label: {
                content: `<div class="alarm-content" style="width: 180px" > 
                                <div style="text-align: center;padding-bottom: 6px">${name}</div>
                                <div style="text-wrap: wrap">${address}</div>
                          </div>`,
                offset: new AMap.Pixel(-100, 55),
            },
        });
        this.map.add(this.emergencyMarker);
        this.setZoomCenter(position);
    },
    /**
     * @desc 清除应急人员Marker
     */
    clearEmergencyMarker() {
        if (this.emergencyMarker) {
            this.emergencyMarker?.setMap(null);
            this.emergencyMarker = null;
        }
    },
    /**
     * @desc 根据坐标获取地址信息
     * @param {Array} list 坐标点数组
     */
    getAddressByPoint(list: number[]) {
        const geocoder = new AMap.Geocoder({
            city: '全国',
            radius: 1000,
        });
        let lnglat = new AMap.LngLat(list[0], list[1]);
        return new Promise((resolve, reject) => {
            geocoder.getAddress(lnglat, (status, result) => {
                if (status === 'complete' && result.regeocode) {
                    return resolve(result.regeocode.formattedAddress, result.regeocode);
                }
                return reject(result);
            });
        });
    },
    /**
     * @desc 清除导航元素
     */
    clearNavigationElements() {
        this.clearNaviLine();
        this.clearEmergencyMarker();
    },
};
